package com.cloud.sms.manager.impl;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cloud.commons.Result;
import com.cloud.commons.utils.CopyObjectUtils;
import com.cloud.sms.api.manager.SmsManager;
import com.cloud.sms.api.req.SmsDefenseCoreVo;
import com.cloud.sms.constant.SmsConstant;
import com.cloud.sms.model.SmsBlacklist;
import com.cloud.sms.model.SmsDefenseCore;
import com.cloud.sms.model.SmsHistory;
import com.cloud.sms.model.SmsWhiteList;
import com.cloud.sms.service.*;
import com.cloud.sms.utils.StringCoreUtils;
import net.sf.ezmorph.object.DateMorpher;
import net.sf.json.JSONObject;
import net.sf.json.util.JSONUtils;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @describe 
 * 
 * @author tc
 * @date 2015年1月23日
 */
@RestController
public class SMSController extends MainController implements SmsManager {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SmsWhiteListService smsWhiteListService;

    @Autowired
    private SmsHistoryService smsHistoryService;

    @Autowired
    private SmsDefenseParamService smsDefenseParamService;

    @Autowired
    private SmsDefenseCoreService smsDefenseCoreService;

    @Autowired
    private SmsBlacklistService smsBlacklistService;

    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * @describe 
     * 
     * @auther ruanpeng
     * @date 2014年8月13日
     * @throws Exception
     */
    @RequestMapping(value = "/test", method = { RequestMethod.GET, RequestMethod.POST })
    public String test(String mobile, HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject obj = new JSONObject();
        response.setContentType("text/html;charset=utf-8");
        obj.put("mobile", mobile);
        String telephoneNo = mobile;
        String templateId = "1673";
        int mobile_code = (int)((Math.random()*9+1)*100000);
        String argstr = mobile_code+"";
        response.getWriter().print(sendSmsHuyi(telephoneNo, templateId, argstr));
        return null;
    }

    // json to javabean
    public static Object getObject4JsonString(String jsonString, Class pojoCalss) {
        Object pojo;
        JSONObject jsonObject = JSONObject.fromObject(jsonString);
        String[] dateFormats = new String[] { "yyyy-MM-dd HH:mm:ss" };
        JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(dateFormats));
        pojo = JSONObject.toBean(jsonObject, pojoCalss);
        return pojo;
    }

    // 措施二：单用户动态短信请求间隔时长限制 ， 服务器端锁定如：30秒后，才能进行第二次动态短信请求。
    public String checkTimeInterval(SmsDefenseCore smsObj) {
        String result = "";
        SmsDefenseCore newSmsObj = smsDefenseCoreService.selectByTelephoneNoLast(smsObj.getTelephoneNo());
        if (newSmsObj != null) {
            long newSmsTimeLong = newSmsObj.getSendTime().getTime();
            long smsTimeLong = new Date().getTime();
            long timeTmp1 = smsTimeLong - newSmsTimeLong;
            int resultTmp = (int) (timeTmp1 / 1000);
            if (resultTmp < 30) {
                // 表示 30秒内再发短信，被禁止						
                result = "{statusCode:\"997\", statusMsg:\"短信请求间隔时小于30秒禁止发送\"}";
            } else {
                // 表示正常，没有问题可以发送短信
                result = saveAndSendSms(smsObj);
            }
        } else {
            // 说明重来没有发过短信，可以正常发
            result = saveAndSendSms(smsObj);
        }
        return result;
    }

    // 保存记录并发送短信
    public String saveAndSendSms(SmsDefenseCore smsObj){

        String result = "";

        // 短信发送历史记录保存据
        SmsHistory historyObj = new SmsHistory();
        historyObj.setTelephoneNo(smsObj.getTelephoneNo());
        historyObj.setIpAddress(smsObj.getIpAddress());
        historyObj.setTemplateId(smsObj.getTemplateId());
        historyObj.setContentParam(smsObj.getContentParam());
        historyObj.setSendTime(new Date());
        smsHistoryService.insertSelective(historyObj);

        // 发送短信
        result = sendSmsHuyi(smsObj.getTelephoneNo(), smsObj.getTemplateId(), smsObj.getContentParam());
        
        //log.info("参数值："+smsObj.getContentParam());
        
        return result;
    }


    // 发短信 
    public static String sendSmsHuyi(String telephoneNo, String templateId, String argstr) {
        String Url = "http://106.ihuyi.cn/webservice/sms.php?method=Submit";
        String resultVal = "";
        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(Url);
        client.getParams().setContentCharset("UTF-8");
        method.setRequestHeader("ContentType", "application/x-www-form-urlencoded;charset=UTF-8");
        String sendTemplate = "";
        if (SmsConstant.SMSWhiteMap.containsKey(templateId)) {
            sendTemplate = argstr;
        } else {
            sendTemplate = SmsConstant.SMSMap.get(templateId);
            if (argstr != null && !"".equals(argstr.trim())) {
                if (argstr.indexOf("|") != -1) {
                    String[] args = argstr.split("\\|");
                    for (int i = 0; i < args.length; i++) {
                        String temp = "{" + i + "}";
                        if (sendTemplate.indexOf(temp) != -1) {
                            sendTemplate = sendTemplate.replace(temp, args[i]);
                        }
                    }
                } else {
                    sendTemplate = sendTemplate.replace("{0}", argstr);
                }
            }
            //检测是否有空参数传递
            for (int i = 0; i < 3; i++) {
                String temp = "{" + i + "}";
                if (sendTemplate.indexOf(temp) != -1) {
                    sendTemplate = sendTemplate.replace(temp, "");
                }
            }
        }

        String content = new String(sendTemplate);
        
        System.out.println("完整短信内容："+content);
        
        NameValuePair[] data = {//提交短信
        new NameValuePair("account", SmsConstant.huyiAccount),
                new NameValuePair("password", StringCoreUtils.MD5Encode(SmsConstant.huyiPassword)),
                new NameValuePair("mobile", telephoneNo), new NameValuePair("content", content), };
        method.setRequestBody(data);
        try {
            client.executeMethod(method);
            String SubmitResult = method.getResponseBodyAsString();
            Document doc = DocumentHelper.parseText(SubmitResult);
            Element root = doc.getRootElement();
            String code = root.elementText("code");
            String msg = root.elementText("msg");
            if ("2".equals(code)) {
                resultVal = "{statusCode:\"000000\", statusMsg:\"短信发送成功\"}";
            } else {
                resultVal = "{statusCode:\"" + code + "\", statusMsg:\"" + msg + "\"}";
            }
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return resultVal;
    }

    /**
     * @describe
     *
     * @auther tc
     * @date 2021年1月13日
     * @throws Exception
     */
    @Override
    public Result sendMessage(SmsDefenseCoreVo smsDefenseCoreVo){
        Result re = new Result() ;
        String result ;
        // 取得短信接口输入数据对象
        SmsDefenseCore smsObj = CopyObjectUtils.copyAtoB(smsDefenseCoreVo, SmsDefenseCore.class);
        smsObj.setSendTime(new Date());

        // 黑名单判断
        SmsBlacklist blackObj = smsBlacklistService.selectByIpAddress(smsObj.getIpAddress());
        if (blackObj == null) {
            blackObj = smsBlacklistService.selectByIpAddress(smsObj.getTelephoneNo());
        }
        if (blackObj != null) {
            return Result.build(-1,"IP地址在黑名单中禁止发送") ;
        } else {

            // 短信防御业务主表插入数据
            smsDefenseCoreService.insertSelective(smsObj);

            // 白名单判断，true不做IP限制
            SmsWhiteList whiteObj = smsWhiteListService.selectByIpAddress(smsObj.getIpAddress());
            if (whiteObj != null) {

                // 措施二： 单用户动态短信请求间隔时长限制 ， 服务器端锁定如：30秒后，才能进行第二次动态短信请求。
                result = checkTimeInterval(smsObj);

            } else {
                // 常规操作采取措施一和二

                // 措施一：单IP的请求次数限定：不超过200个/分钟。
                Calendar currCale = Calendar.getInstance();
                String endTime = format.format(currCale.getTime());
                currCale.add(Calendar.MINUTE, -1);
                String startTime = format.format(currCale.getTime());
                int smsNum = smsDefenseCoreService.countIpLimit(smsObj.getIpAddress(), startTime, endTime);
                if (smsNum < 200) {

                    // 措施二： 单用户动态短信请求间隔时长限制 ， 服务器端锁定如：30秒后，才能进行第二次动态短信请求。
                    result = checkTimeInterval(smsObj);

                } else {
                    // 加入黑名单
                    SmsBlacklist newBlackObj = new SmsBlacklist();
                    newBlackObj.setIpAddress(smsObj.getIpAddress());
                    newBlackObj.setCreateTime(new Date());
                    smsBlacklistService.insertSelective(newBlackObj);
                    result = "{statusCode=\"998\", statusMsg=\"单IP请求次数一分钟大于200，锁定IP黑名单，禁止发送\"}";
                }
            }
        }
        re.setData(result);
        return re;
    }

    public static void main(String[] args) {
        String telephoneNo = "15989837031";
        String templateId = "1";
        String argstr = "8244088";
        System.out.print(sendSmsHuyi(telephoneNo, templateId, argstr));
    }
}
